package model;

import java.util.List;
import java.util.Iterator;


/**
 * A simple model of a fox.
 * Foxes age, move, eat rabbits, and die.
 * Update; they can also breed
 * 
 * @author Team X
 * @version 1
 */
public class Fox extends Animal
{
	// The age at which a fox can start to breed.
    private static final int DEF_BREEDING_AGE = 10;
    // The age to which a fox can live.
    private static final int DEF_MAX_AGE = 40;
    // The likelihood of a fox breeding.
    private static final double DEF_BREEDING_PROBABILITY = 0.03;
    // The maximum number of births.
    private static final int DEF_MAX_LITTER_SIZE = 3;

    public static int breeding_age = DEF_BREEDING_AGE;
    public static int max_age = DEF_MAX_AGE;
    public static double breeding_probability = DEF_BREEDING_PROBABILITY;
    public static int max_litter_size = DEF_MAX_LITTER_SIZE;
    
    // number of steps a fox can go before it has to eat again.
    private static final int RABBIT_FOOD_VALUE = 7;
    
    /**
     * Create a fox. A fox can be created as a new born (age zero
     * and not hungry) or with a random age and food level.
     * 
     * @param randomAge If true, the fox will have random age and hunger level.
     * @param field The field currently occupied.
     * @param location The location within the field.
     */
    public Fox(boolean randomAge, Field field, Location location)
    {
        super(randomAge,field, location);
        food = RABBIT_FOOD_VALUE;
    }
    
    /**
     * This is what the fox does most of the time: it hunts for
     * rabbits. In the process, it might breed, die of hunger,
     * or die of old age.
     * @param field The field currently occupied.
     * @param newFoxes A list to add newly born foxes to.
     */
    public void act(List<Animal> newFoxes)
    {
        incrementAge();
        incrementHunger();
        becomeSick();
        if(isAlive()) 
        {
        	// Give baby foxes
            giveBirth(newFoxes);            
            
            // Move towards a source of food if found.
            Location location = getLocation();
            // Find food
            Location newLocation = findFood(location);
            
            if(newLocation == null) 
            { 
                // No food found - try to move to a free location.
                newLocation = getField().freeAdjacentLocation(location);
            }
            // See if it was possible to move.
            if(newLocation != null) 
            {
                setLocation(newLocation);
            }
            else 
            {
                // Overcrowding.
                setDead();
            }
        }
    }

    /**
     * Tell the fox to look for rabbits adjacent to its current location.
     * Only the first live rabbit is eaten.
     * @param location Where in the field it is located.
     * @return Where food was found, or null if it wasn't.
     */
    private Location findFood(Location location)
    {
        Field field = getField();
        List<Location> adjacent = field.adjacentLocations(getLocation());
        Iterator<Location> it = adjacent.iterator();
        while(it.hasNext()) 
        {
            Location where = it.next();
            Object animal = field.getObjectAt(where);
            if(animal instanceof Rabbit) 
            {
                Rabbit rabbit = (Rabbit) animal;
                if(rabbit.isAlive()) 
                { 
                    rabbit.setDead();
                    food = RABBIT_FOOD_VALUE;
                    // Remove the dead rabbit from the field.
                    return where;
                }
            }
        }
        return null;
    }
    
    /**
     * Get breeding age
     * @return breeding age
     */
	public int getBreedingAge() 
	{
		return breeding_age;
	}
	
    /**
     * Get the maximum age
     * @return max age
     */
	public int getMaxAge() 
	{
		return max_age;
	}
	
    /**
     * Get the max amount of litter a fox can have
     * @return litter size
     */
	public int getMaxLitterSize() 
	{
		return max_litter_size;
	}

	/**
	 * Get breeding probability
	 * @return breeding_probability;
	 */
	public double getBreedingprobability() 
	{
		return breeding_probability;
	}
	
	/**
	 * Setter van de breeding age
	 */
	public void setBreedingAge(int age)
	{
		breeding_age = age;
	}
	
	/**
	 * Setter max age
	 */
    public void setMaxAge(int age)
    {
    	max_age = age;
    }
    
	/**
	 * Setter breeding probability
	 */
    public void setBreedingprobability(double probability)
    {
    	breeding_probability = probability;
    }
    
	/**
	 * Setter maximum babies it can get
	 */
    public void setMaxLitterSize(int age)
    {
    	max_litter_size = age;
    }
    
    /**
     * Set back the basic values
     * @see model.Animal#reset()
     */
	public void reset() 
	{
		breeding_age = DEF_BREEDING_AGE;
		max_age = DEF_MAX_AGE;
		breeding_probability = DEF_BREEDING_PROBABILITY;
	    max_litter_size = DEF_MAX_LITTER_SIZE;		
	}
	
	/**
	 * Reset values
	 */
	public static void defReset() 
	{
		breeding_age = DEF_BREEDING_AGE;
		max_age = DEF_MAX_AGE;
		breeding_probability = DEF_BREEDING_PROBABILITY;
	    max_litter_size = DEF_MAX_LITTER_SIZE;		
	}
	
    /**
     * Check whether or not this fox  to give birth at this step.
     * New births will be made into free adjacent locations.
     * @param newFoxes A list to add newly born foxes.
     */
    protected void giveBirth(List<Animal> newFoxes)
    {
        // New foxes are born into adjacent locations.
        // Get a list of adjacent free locations.
        Field field = getField();
        List<Location> free = field.getFreeAdjacentLocations(getLocation());
        int births = breed();
        for(int b = 0; b < births && free.size() > 0; b++) 
        {
            Location loc = free.remove(0);
            Fox young = new Fox(false, field, loc);
            newFoxes.add(young); 
        }
    }
    
    /**
     * Method to return the character info of the foxes actor
     * @return a arraylist with the character info
     */
	public static int[] getCharacterInfo() 
	{
		int[] returnArray = new int[10];
		returnArray[0] = breeding_age ;
		returnArray[1] = max_age ;
		returnArray[2] = max_litter_size;
		return returnArray;		
	}

	public static double getBreedingProbability() 
	{
		return breeding_probability;
	}
	
	/**
     * Change foxes Characteristics
     */
    public static void changeCharacteristics(String itemToChange, double value) 
    {
    	if (itemToChange.equals("breeding_age"))
    		breeding_age = (int)value;
    	if (itemToChange.equals("max_age"))
    		max_age = (int)value;
    	if (itemToChange.equals("breeding_probability"))
    		breeding_probability = value;
    	if (itemToChange.equals("max_litter_size"))
    		max_litter_size = (int)value;
    }
    
    public static void changeBreedingAge (int value)
    {
    	breeding_age = value;
    }
    
    public static void changeMaxAge(int value)
    {
    	max_age = value;
    }
    
    public static void changeLitterSize(int value)
    {
    	max_litter_size = value;
    }
    
    public static void changeBreedingProbability(int value)
    {
    	breeding_probability = value;
    }
}
